home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / lptalk-1.3 / stuff.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  9KB  |  356 lines

  1. /************************************************************************/
  2. /* LP-Talk
  3.     Version 1.0 [ 9/24/90]
  4. 26-Sep-90, shawnm, fixed output of partial lines
  5.             1.1 [ 9/27/90]
  6.             1.2 [ 9/28/90]
  7. */
  8. /* TinyTalk: the real good stuff (network connections, main loop).    */
  9. /*                                    */
  10. /*    Version 1.0 [ 1/24/90] : Initial implementation by ABR.        */
  11. /*            1.1 [ 1/25/90] : Changed for systems without FD_SET.    */
  12. /*        1.2 [ 1/26/90] : Added "quiet" and "nologin" control.    */
  13. /*        1.3 [ 1/27/90] : Increased max number of 'quiet' lines.    */
  14. /*        1.4 [ 2/ 2/90] : Moved out special output handling.     */
  15. /*                 Changed connection processing.        */
  16. /*        1.5 [ 2/ 5/90] : Modify to handle switching MUDs more   */
  17. /*                 cleanly.  Fix gag problem.        */
  18. /*        1.6 [ 2/16/90] : Integrated support for System V and    */
  19. /*                 HP-UX, from Andy Norman and Kipp       */
  20. /*                 Hickman.                */
  21. /*                                    */
  22. /************************************************************************/
  23.  
  24. #include "tl.h"
  25. #include <sys/types.h>
  26. #include <sys/time.h>
  27. #include <sys/socket.h>
  28. #include <netdb.h>
  29. #include <netinet/in.h>
  30. #include <fcntl.h>
  31. #include <sys/errno.h>
  32. #include <stdio.h>
  33.  
  34.   /* For some odd systems, which don't put this in errno.h. */
  35.  
  36. extern int errno;
  37.  
  38.   /* For BSD 4.2 systems. */
  39.  
  40. #ifndef FD_ZERO
  41. #define DESCR_MASK int
  42. #define FD_ZERO(p) (*p = 0)
  43. #define FD_SET(n,p) (*p |= (1<<(n)))
  44. #define FD_ISSET(n,p) (*p & (1<<(n)))
  45. #else
  46. #define DESCR_MASK fd_set        /* For BSD 4.3 systems. */
  47. #endif
  48.  
  49.   /* End of BSD 4.2 systems. */
  50.  
  51. #define REFRESH_TIME 500000        /* Microseconds */
  52.  
  53. extern char *index(), *malloc();
  54. extern struct hostent *gethostbyname();
  55. extern unsigned long inet_addr();
  56. extern world_rec *find_world();
  57.  
  58. extern int do_not_echo;            /* so don't echo passwords */
  59.  
  60. static world_rec *current_world;
  61. static int current_socket;
  62. static int connected;            /* Are we connected anywhere? */
  63. hugestr current_output;            /* Queued as messages arrive. */
  64. static int need_refresh;        /* Does input line need refresh? */
  65. static int done;            /* Are we all done? */
  66. static int use_magic_login;        /* Auto-logins enabled? */
  67. static int flush_pending_output;    /* For portals. */
  68.  
  69. do_stuff(initial_world)
  70.   world_rec *initial_world;
  71. {
  72.   int count;
  73.   DESCR_MASK readers, exceptions;
  74.   struct timeval refresh_timeout;
  75.   struct timeval *tv;
  76.  
  77.   flush_pending_output = FALSE;
  78.  
  79.   connected = FALSE;
  80.   if (!connect_to(initial_world))
  81.     die("%% Couldn't connect to initial world.\n");
  82.  
  83.   *current_output = '\0';        /* No output yet. */
  84.  
  85.   done = FALSE;
  86.  
  87.   need_refresh = 0;            /* No keyboard typing yet. */
  88.  
  89.     sleep(1);            /* Wait a second after connect */
  90.   magic_login();            /* Log us in, if possible. */
  91.  
  92.   do {
  93.     flush_pending_output = FALSE;    /* No output is pending, ignore any */
  94.                     /* attempts to flush it. */
  95.  
  96.     FD_ZERO(&readers);
  97.     FD_ZERO(&exceptions);
  98.     FD_SET(0, &readers);        /* Check standard input. */
  99.     FD_SET(current_socket, &readers);    /* Check socket. */
  100.  
  101.     if (need_refresh) {
  102.       refresh_timeout.tv_sec = 0;
  103.       refresh_timeout.tv_usec = REFRESH_TIME;
  104.       tv = &refresh_timeout;
  105.     }
  106.     else
  107.       tv = NULL;
  108.  
  109.     count = select(current_socket + 1, &readers, NULL, &exceptions, tv);
  110.     if (count == -1) {
  111.       if (errno != EINTR)        /* Control-Z will do this. */
  112.     perror("select");
  113.     }
  114.     else if (count == 0)
  115.       do_refresh();
  116.     else {
  117.       if (FD_ISSET(current_socket, &readers))
  118.     handle_socket_input();
  119.       else if (FD_ISSET(0, &readers)) {
  120.     if (need_refresh)
  121.       do_refresh();
  122.     handle_keyboard_input();
  123.       }
  124.       else
  125.     fprintf(stderr,"%% ??select??");
  126.     }
  127.  
  128.   } while (!done);
  129.  
  130.   disconnect();
  131.   cleanup_keyboard();
  132. }
  133.  
  134. int connect_to(w)            /* Try to make a connection. */
  135.   register world_rec *w;
  136. {
  137.   struct in_addr host_address;
  138.   struct sockaddr_in socket_address;
  139.   int err;
  140.  
  141.   register world_rec *temp_world;    /* Use temporaries until we know */
  142.   register int temp_socket;        /* that we've succeeded! */
  143.  
  144.   temp_world = w;
  145.   if (!get_host_address(w->address, &host_address)) { /* Can't do it. */
  146.     return(0);
  147.   }
  148.  
  149.   socket_address.sin_family = AF_INET;
  150.   socket_address.sin_port = htons(atoi(w->port));
  151.   bcopy(&host_address, &socket_address.sin_addr, sizeof(struct in_addr));
  152.  
  153.   temp_socket = socket(AF_INET, SOCK_STREAM, 0);
  154.   if (temp_socket < 0) {
  155.     perror("% Couldn't open socket");
  156.     return(0);
  157.   }
  158.  
  159.   err = connect(temp_socket, &socket_address, sizeof(struct sockaddr_in));
  160.   if (err < 0) {
  161.     perror("% Couldn't connect to socket");
  162.     return(0);
  163.   }
  164.  
  165. #ifdef FNDELAY
  166.   fcntl(temp_socket, F_SETFL, FNDELAY);    /* Do we need this? */
  167. #endif
  168.  
  169.   if (connected)            /* Disconnect from any open world. */
  170.     disconnect();
  171.  
  172.   current_world = temp_world;
  173.   current_socket = temp_socket;
  174.  
  175.   connected = TRUE;
  176.   return(1);                /* Success! */
  177. }
  178.  
  179. int get_host_address(name, addr)    /* Get a host address. */
  180.   register char *name;
  181.   register struct in_addr *addr;
  182. {
  183.   struct hostent *blob;
  184.   union {                /* %#@!%!@%#!@ idiot who designed */
  185.     long signed_thingy;            /* the inetaddr routine.... */
  186.     unsigned long unsigned_thingy;
  187.   } thingy;
  188.  
  189.   if (*name == '\0') {
  190.     fprintf(stderr, "%% No host address specified.\n");
  191.     return (0);
  192.   }
  193.  
  194.   if ((*name >= '0') && (*name <= '9')) {    /* IP address. */
  195.     addr->s_addr = inet_addr(name);
  196.     thingy.unsigned_thingy = addr->s_addr;
  197.     if (thingy.signed_thingy == -1) {
  198.       fprintf(stderr, "%% Couldn't find host %s .\n", name);
  199.       return (0);
  200.     }
  201.   }
  202.   else {                /* Host name. */
  203.     blob = gethostbyname(name);
  204.  
  205.     if (blob == NULL) {
  206.       fprintf(stderr, "%% Couldn't find host %s .\n", name);
  207.       return (0);
  208.     }
  209.  
  210.     bcopy(blob->h_addr, addr, sizeof(struct in_addr));
  211.   }
  212.  
  213.   return (1);                /* Success. */
  214. }
  215.  
  216. disconnect()                /* Disconnect from current world. */
  217. {
  218.   if (connected) {
  219.     flush_pending_output = TRUE;    /* Flush pending output.  This is */
  220.     current_output[0] = '\0';        /* used when switching worlds. */
  221.     close(current_socket);
  222.   }
  223.  
  224.   connected = FALSE;
  225. }
  226.  
  227. transmit(s, l)                /* Send a message over the socket. */
  228.   char *s;
  229.   int l;
  230. {
  231.   register int err;
  232.  
  233.   err = send(current_socket, s, l, 0);
  234.   if (err == -1)
  235.     perror("send failed");
  236. }
  237.  
  238. receive(s)
  239.   register char *s;
  240. {
  241.   register int count;
  242.  
  243.   count = recv(current_socket, s, MAXSTRLEN, 0);
  244.   if (count == -1) {
  245.     if (errno == EWOULDBLOCK)
  246.       s[0] = '\0';
  247.     else {
  248.       perror("recv failed");
  249.     }
  250.   }
  251.   else
  252.     s[count] = '\0';
  253.  
  254.   if (count <= 0)            /* Don't ask me. */
  255.     done = TRUE;
  256. }
  257.  
  258. magic_login()
  259. {
  260.   string s;
  261.   register world_rec *def;
  262.  
  263.   if (!use_magic_login)            /* Check if auto-login is enabled. */
  264.     return;
  265.  
  266.   if (*(current_world->character) == '\0') { /* Try default world. */
  267.     def = find_world("default");
  268.     if (def == NULL) {
  269.       return;
  270.     }
  271.     else {
  272.       sprintf(s,"%s\n", def->character);
  273.       transmit(s, strlen(s));
  274.       sleep(2);                /* wait a second after name */
  275.       sprintf(s,"%s\n", def->pass);
  276.       transmit(s, strlen(s));
  277.       start_quiet();            /* Suppress login messages? */
  278.       do_not_echo = FALSE;
  279.       return;
  280.     }
  281.   }
  282.   else {
  283.     sprintf(s,"%s\n", current_world->character);
  284.     transmit(s, strlen(s));
  285.     sleep(2);                /* wait a second after name */
  286.     sprintf(s,"%s\n", current_world->pass);
  287.     transmit(s, strlen(s));
  288.     start_quiet();            /* Suppress login message? */
  289.     do_not_echo = FALSE;
  290.     return;
  291.   }
  292. }
  293.  
  294. clear_refresh_pending()
  295. {
  296.   need_refresh = 0;
  297. }
  298.  
  299. set_refresh_pending()
  300. {
  301.   need_refresh = 1;
  302. }
  303.  
  304. handle_socket_input()
  305. {
  306.   string blob;
  307.   hugestr bigblob;
  308.   register char *place;
  309.   int len;
  310.  
  311.   receive(blob);
  312.   strcat(current_output, blob);        /* Concatenate this bunch of input. */
  313.  
  314.   place = index(current_output, '\n');    /* Output any whole lines. */
  315.   if (place != NULL) {
  316.     while (place != NULL) {
  317.       *place = '\0';
  318.       if (!special_hook(current_output))
  319.     print_with_wrap(current_output);
  320.       if (flush_pending_output) {    /* Flush the buffer. */
  321.     flush_pending_output = FALSE;
  322.     *current_output = '\0';
  323.     return;
  324.       }
  325.       strcpy(bigblob, place + 1);    /* Rest of buffer. */
  326.       strcpy(current_output, bigblob);    /* Copy it back to buffer. */
  327.       place = index(current_output, '\n');
  328.     }
  329.   }
  330.  
  331.   do_not_echo = FALSE;
  332.   len = strlen(current_output);
  333.   if (len > 0) { /* Do partial line. */
  334.     if (len > 9) /* Check for password entry */
  335.         if (equalstr((current_output + len - 10), "password: "))
  336.             do_not_echo = TRUE;
  337.     print_partial_line(current_output);
  338.     *current_output = '\0';        /* Flush the buffer. */
  339.   }
  340. }
  341.  
  342. enable_auto_login()
  343. {
  344.   use_magic_login = TRUE;
  345. }
  346.  
  347. disable_auto_login()
  348. {
  349.   use_magic_login = FALSE;
  350. }
  351.  
  352. set_done()                /* Used by /QUIT command to exit */
  353. {                    /* cleanly. */
  354.   done = TRUE;
  355. }
  356.